﻿using System.IO.Ports;
using System.Net;
using System.Net.Sockets;
using System.Windows;
using Serilog;

namespace ZDriver;

public class Udp_Driver
{
    // 是否正在监听
    private bool _isListening;

    // UDP handle
    private UdpClient? _udp;

    /// <summary>
    ///     UDP 驱动实例
    /// </summary>
    public Udp_Driver()
    {
    }

    // 定义数据接收事件
    public event EventHandler<byte[]>? DataReceived;

    /// <summary>
    ///     获得当前所有的UDP 名称
    /// </summary>
    public static string[] GetPortNames()
    {
        return SerialPort.GetPortNames();
    }

    /// <summary>
    ///     是否打开UDP,处于监听状态
    /// </summary>
    /// <returns>true表示已经打开,false则没有</returns>
    public bool IsOpen()
    {
        return _udp != null && _isListening;
    }

    /// <summary>
    ///     打开UDP,如果已经打开则先关闭,再打开
    /// </summary>
    public void Open(string ip, int port)
    {
        if (_isListening) Close();

        try
        {
            _udp = new UdpClient(new IPEndPoint(IPAddress.Parse(ip), port));
            _isListening = true;

            // 开始异步接收消息
            Task.Run(async () => await OnDataReceived());
        }
        catch (Exception ex)
        {
            MessageBox.Show($"启动监听失败: {ex.Message}");
            _isListening = false;
        }
    }
    
    /// <summary>
    ///     打开UDP,如果已经打开则先关闭,再打开
    /// </summary>
    public void Open(int port)
    {
        if (_isListening) Close();

        try
        {
            _udp = new UdpClient(new IPEndPoint(IPAddress.Any, port));
            _isListening = true;

            // 开始异步接收消息
            Task.Run(async () => await OnDataReceived());
        }
        catch (Exception ex)
        {
            MessageBox.Show($"启动监听失败: {ex.Message}");
            _isListening = false;
        }
    }

    /// <summary>
    ///     关闭UDP
    /// </summary>
    public void Close()
    {
        _isListening = false;
        _udp?.Close();
    }

    /// <summary>
    ///     写入数据到UDP
    /// </summary>
    /// <param name="data">待写入数据</param>
    /// <param name="remoteEp">目标地址</param>
    public async Task Write(byte[] data, IPEndPoint remoteEp)
    {
        try
        {
            await _udp!.SendAsync(data, data.Length, remoteEp);
        }
        catch (Exception ex)
        {
            Log.Warning($"发送失败:{ex.Message}");
        }
    }

    /// <summary>
    ///     接收数据
    /// </summary>
    private async Task OnDataReceived()
    {
        while (_isListening && _udp != null)
            try
            {
                var result = await _udp.ReceiveAsync();
                var data = result.Buffer;
                DataReceived?.Invoke(this, data);
            }
            catch (ObjectDisposedException)
            {
                // UdpClient已被释放，正常退出
                break;
            }
            catch (Exception)
            {
                // Log.Warning($"[udp接收错误] {e.Message}");
                break;
            }
    }
}